/**
 * @file cmd_ver.c
 * @brief 
 * @author henry.cai (henry.cai@queclink.com)
 * @version 1.0
 * @date 2024-09-05
 * 
 * @copyright Copyright (C) 2019 Queclink Wireless Solutions (ShenZhen) Co., Ltd. All Rights Reserved.
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2024-09-05 <td>1.0     <td>henry.cai     <td>内容
 * </table>
 */
#include <stdio.h>
#include <stdint.h>
#include "lettershell/shell.h"
#include "../shell_log.h"
#include "misc/hwmisc.h"
#include "misc/version.h"

#include "global.h"

#include "modem/qlmodem/include/qlmodemconfdefs.h"
#include "mmgr/include/mmgr_modem.h"

#define MAX_VER_LEN (48)
struct ver_t {
    const char  *obj;
    int32_t         (*getver)(char ver[MAX_VER_LEN + 1]);
};

#ifndef ARRAY_COUNT
#define ARRAY_COUNT(array)  (sizeof(array) / sizeof(array[0]))
#endif


/// @brief 获取硬件版本号
/// @param ver 
/// @return 
int32_t  shcmd_get_hw_ver(char ver[48])
{
    snprintf(ver, MAX_VER_LEN + 1, "%s", get_hw_ver());
    return 0;
}


#include "misc/version.h"
const bootloader_info_t *boot = (bootloader_info_t *)(FW_START_ADDR + 800);

/// @brief 获取boot版本
/// @param ver 
/// @return 
int32_t  shcmd_get_bootloader_ver(char ver[48])
{
    snprintf(ver, MAX_VER_LEN + 1, "%s(%s)", boot->version, boot->timestamp);
    return 0;
}

/// @brief 获取软件实际版本
/// @param ver 
/// @return 
int32_t  shcmd_get_fw_ver(char ver[48])
{
    snprintf(ver, MAX_VER_LEN + 1, "%s", SOFTWARE_VERSION);
    return 0;
}

/// @brief 获取modem版本号
/// @param ver 
/// @return 
int32_t  shcmd_get_mdm_fw_ver(char ver[48])
{
    snprintf(ver, MAX_VER_LEN + 1, "%s,%s", qlmodem_version, mmgr_version_get());
    return 0;
}

/// @brief 获取co-mcu固件版本号
/// @param ver 
/// @return 
int32_t  shcmd_get_comcu_fw_ver(char ver[48])
{
    snprintf(ver, MAX_VER_LEN + 1, "%s", "need implement!");
    return 0;
}

/// @brief 获取蓝牙版本号
/// @param ver 
/// @return 
int32_t  shcmd_get_ble_fw_ver(char ver[48])
{
    snprintf(ver, MAX_VER_LEN + 1, "%s", "need implement!");
    return 0;
}

/// @brief 获取电控版本号
/// @param ver 
/// @return 
int32_t  shcmd_get_ecu_fw_ver(char ver[48])
{
    snprintf(ver, MAX_VER_LEN + 1, "%s", "need implement!");
    return 0;
}

/// @brief 获取BMS实际版本号
/// @param ver 
/// @return 
int32_t  shcmd_get_bms_fw_ver(char ver[48])
{
    snprintf(ver, MAX_VER_LEN + 1, "%s", "need implement!");
    return 0;
}

/// @brief 获取软件认证版本
/// @param ver 
/// @return 
int32_t  shcmd_get_sw_certver(char ver[48])
{
    snprintf(ver, MAX_VER_LEN + 1, "%s", FIRWARE_CERT_VERSION);
    return 0;
}


/// @brief 获取硬件认证版本
/// @param ver 
/// @return 
int32_t  shcmd_get_hw_certver(char ver[48])
{
    snprintf(ver, MAX_VER_LEN + 1, "%s", HARDWARE_CERT_VERSION);
    return 0;
}

#include "task_gnss.h"
/// @brief 获取GPS版本信息
/// @param ver 
/// @return 
int32_t  shcmd_get_gps_fw_ver(char ver[48])
{
    char gps_ver[GNSS_FW_VER_LEN + 1] = {0};
    qltask_gnss_firmware_version(gps_ver, sizeof(gps_ver));

    snprintf(ver, sizeof(ver), "%s", gps_ver);
    return 0;
}






/* 特别地, 未包含 "cert" 的处理, 支持指令version xxx获取版本信息 */
static const struct ver_t ver_table[] = {
    { "hw",    shcmd_get_hw_ver  },
    { "boot",  shcmd_get_bootloader_ver },
    { "fw",    shcmd_get_fw_ver },
    { "modem", shcmd_get_mdm_fw_ver },
    { "co-mcu", shcmd_get_comcu_fw_ver},
    { "ble",    shcmd_get_ble_fw_ver },
    { "ecu",    shcmd_get_ecu_fw_ver },
    { "bms",    shcmd_get_bms_fw_ver },
    { "gps",    shcmd_get_gps_fw_ver },
};

const struct ver_t *ver_table_search(const char *obj)
{
    int32_t i;

    for (i=0; i < ARRAY_COUNT(ver_table); i++) {
        if (!strcmp(ver_table[i].obj, obj))
            return &ver_table[i];
    }

    return NULL;
}



/**
 * @brief version 命令处理函数
 * @param  argc             My Param doc
 * @param  argv             My Param doc
 * @return int32_t 
 */
int32_t cmd_ver(int32_t argc, char * const argv[])
{
    char ver[48];
    const struct ver_t *pver;
    int r1, r2;
    int i;

    if (1 == argc) { /* "ver" */
        printf("send [version hw]\t\t    get the version of the iot hardware.\r\n");
        printf("send [version boot]\t    get the version of the iot boot.\r\n");
        printf("send [version fw]\t\t    get the version of the iot software.\r\n");
        printf("send [version modem]\t    get the version of the modem.\r\n");
        printf("send [version co-mcu]\t\t    get the version of the co-mcu.\r\n");
        printf("send [version ble]\t\t    get the version of the ble.\r\n");
        printf("send [version ecu]\t\t    get the version of the ecu.\r\n");
        printf("send [version bms]\t\t    get the version of the bms.\r\n");
    } else { 
        /* "ver xxx" or "ver xxx xxx" */
        /* 输出版本信息, 当输入多个参数时, 遇到不支持的参数, 打印 ERROR 并结束 */
        for (i=1; i < argc; i++) {
            if (!strcmp((const char *)argv[i], "cert")) {
                r1 = shcmd_get_sw_certver(ver);
                if (!r1)
                    printf("Software certification version: %s\r\n", ver);
                r2 = shcmd_get_hw_certver(ver);
                if (!r2)
                    printf("Hardware certification version: %s\r\n", ver);
                if ((0 > r1) &&
                    (0 > r2))
                    return -EIO;
            } else if (NULL != (pver = ver_table_search((const char *)argv[i]))) {
                if (0 == pver->getver(ver))
                    printf("%s\r\n", ver);
                else
                    return -EIO;
            } else {
                return -EIO;
            }
        }
   
    }
    
    return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_DISABLE_RETURN,
                 version, cmd_ver, Displays the version information);
